﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace CaptchaLib
{
    public class Captcha
    {
        public string Text { set; get; }
        public Bitmap Image { set; get; }
        public int Width { set; get; }
        public int Height { set; get; }

        private Random random = new Random();

        public void RandomImage(string strTemp, int nWidth, int nHeight)
        {
            Text = strTemp;

        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                Image.Dispose();
            }
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
            this.Dispose(true);
        }

        private void SetDimensions(int nWidth, int nHeight)
        { 
            if(nWidth <= 0)
            {
                throw new ArgumentOutOfRangeException("Width", nWidth, "Argument out of range, must be greater than zero.");
            }

            if (nHeight <= 0)
            {
                throw new ArgumentOutOfRangeException("Height", nHeight, "Argument out of range, must be greater than zero.");
            }

            this.Width = nWidth;
            this.Height = nHeight;
        }

        private void GenerateImage()
        {
            Bitmap bitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppArgb);
            
            Graphics graphic = Graphics.FromImage(bitmap);
            graphic.SmoothingMode = SmoothingMode.AntiAlias;
            
            Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
            HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White);

            graphic.FillRectangle(hatchBrush, rect);

            SizeF size;
            float fontSize = rect.Height + 1;
            Font font; 

            do
            {
                fontSize--;
                font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Bold);
                size = graphic.MeasureString(this.Text, font);

            }while(size.Width > rect.Width);

            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            GraphicsPath path = new GraphicsPath();
            path.AddString(this.Text, font.FontFamily, (int)font.Style, 75, rect, format);

            float v = 4F;
            PointF[] points =
            {
                new PointF(this.random.Next(rect.Width)/v, this.random.Next(rect.Height)/v),
                new PointF(rect.Width - this.random.Next(rect.Width)/v, this.random.Next(rect.Height)/v),
                new PointF(this.random.Next(rect.Width)/v, rect.Height - this.random.Next(rect.Height)/v),
                new PointF(rect.Width - this.random.Next(rect.Width)/v, rect.Height - this.random.Next(rect.Height)/v)
            };

            Matrix matrix = new Matrix();
            matrix.Translate(0F, 0F);
            path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);
            hatchBrush = new HatchBrush(HatchStyle.Percent10, Color.Black, Color.SkyBlue);

            graphic.FillPath(hatchBrush, path);

            int m = Math.Max(rect.Width, rect.Height);
            for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++)
            {
                int x = this.random.Next(rect.Width);
                int y = this.random.Next(rect.Height);
                int w = this.random.Next(m / 50);
                int h = this.random.Next(m / 50);

                graphic.FillEllipse(hatchBrush, x, y, w, h);
            }

            font.Dispose();
            hatchBrush.Dispose();
            graphic.Dispose();

            this.Image = bitmap;

        }
    }
}
